home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Personal Computer World 2009 February
/
PCWFEB09.iso
/
Software
/
Linux
/
Kubuntu 8.10
/
kubuntu-8.10-desktop-i386.iso
/
casper
/
filesystem.squashfs
/
etc
/
init.d
/
alsa-utils
< prev
next >
Wrap
Text File
|
2008-09-25
|
10KB
|
388 lines
#!/bin/sh
#
# alsa-utils initscript
#
### BEGIN INIT INFO
# Provides: alsa-utils
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: S
# Default-Stop: 0 6
# Short-Description: Restore and store ALSA driver settings
# Description: This script stores and restores mixer levels on
# shutdown and bootup.On sysv-rc systems: to
# disable storing of mixer levels on shutdown,
# remove /etc/rc[06].d/K50alsa-utils. To disable
# restoring of mixer levels on bootup, rename the
# "S50alsa-utils" symbolic link in /etc/rcS.d/ to
# "K50alsa-utils".
### END INIT INFO
# Don't use set -e; check exit status instead
# Exit silently if package is no longer installed
[ -x /sbin/alsactl ] || exit 0
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MYNAME=/etc/init.d/alsa-utils
. /lib/lsb/init-functions
# $1 EXITSTATUS
# [$2 MESSAGE]
log_action_end_msg_and_exit()
{
log_action_end_msg "$1" ${2:+"$2"}
exit $1
}
# $1 PROGRAM
executable()
{
# If which is not available then we must be running before
# /usr is mounted on a system that has which in /usr/bin/.
# Conclude that $1 is not executable.
[ -x /bin/which ] || [ -x /usr/bin/which ] || return 1
which "$1" >/dev/null 2>&1
}
# Wait for filesystems to show up
while [ ! -d /usr/bin -o ! -d /var/lib/alsa ]; do
sleep 0.2
done
executable amixer || { echo "${MYNAME}: Error: No amixer program available." >&2 ; exit 1 ; }
bugout() { echo "${MYNAME}: Programming error" >&2 ; exit 123 ; }
# $1 <card ID> | "all"
restore_levels()
{
[ -f /var/lib/alsa/asound.state ] || return 1
CARD="$1"
[ "$1" = all ] && CARD=""
# Assume that if alsactl prints a message on stderr
# then it failed somehow. This works around the fact
# that alsactl doesn't return nonzero status when it
# can't restore settings for the card
if MSG="$(alsactl restore $CARD 2>&1 >/dev/null)" && [ ! "$MSG" ] ; then
return 0
else
# Retry with the "force" option. This restores more levels
# but it results in much longer error messages.
alsactl -F restore $CARD >/dev/null 2>&1
[ -z "$CARD" ] && log_action_cont_msg "warning: 'alsactl restore' failed with error message '$MSG'"
return 1
fi
}
# $1 <card ID> | "all"
store_levels()
{
CARD="$1"
[ "$1" = all ] && CARD=""
if MSG="$(alsactl store $CARD 2>&1)" ; then
sleep 1
return 0
else
[ -z "$CARD" ] && log_action_cont_msg "warning: 'alsactl store' failed with error message '$MSG'"
return 1
fi
}
echo_card_indices()
{
if [ -f /proc/asound/cards ] ; then
sed -n -e's/^[[:space:]]*\([0-7]\)[[:space:]].*/\1/p' /proc/asound/cards
fi
}
filter_amixer_output()
{
sed \
-e '/Unable to find simple control/d' \
-e '/Unknown playback setup/d' \
-e '/^$/d'
}
# The following functions try to set many controls.
# No card has all the controls and so some of the attempts are bound to fail.
# Because of this, the functions can't return useful status values.
# $1 <control>
# $2 <level>
# $CARDOPT
unmute_and_set_level()
{
{ [ "$2" ] && [ "$CARDOPT" ] ; } || bugout
amixer $CARDOPT -q set "$1" "$2" unmute 2>&1 | filter_amixer_output || :
return 0
}
# $1 <control>
# $CARDOPT
mute_and_zero_level()
{
{ [ "$1" ] && [ "$CARDOPT" ] ; } || bugout
amixer $CARDOPT -q set "$1" "0%" mute 2>&1 | filter_amixer_output || :
return 0
}
# $1 <control>
# $2 "on" | "off"
# $CARDOPT
switch_control()
{
{ [ "$2" ] && [ "$CARDOPT" ] ; } || bugout
amixer $CARDOPT -q set "$1" "$2" 2>&1 | filter_amixer_output || :
return 0
}
# $1 <card ID>
sanify_levels_on_card()
{
CARDOPT="-c $1"
unmute_and_set_level "Front" "80%"
unmute_and_set_level "Master" "80%"
unmute_and_set_level "Master Mono" "80%" # See Bug#406047
unmute_and_set_level "Master Digital" "80%" # E.g., cs4237B
unmute_and_set_level "Playback" "80%"
unmute_and_set_level "Headphone" "70%"
unmute_and_set_level "PCM" "80%"
unmute_and_set_level "PCM,1" "80%" # E.g., ess1969
unmute_and_set_level "DAC" "80%" # E.g., envy24, cs46xx
unmute_and_set_level "DAC,0" "80%" # E.g., envy24
unmute_and_set_level "DAC,1" "80%" # E.g., envy24
unmute_and_set_level "Synth" "80%"
unmute_and_set_level "CD" "80%"
mute_and_zero_level "Mic"
mute_and_zero_level "IEC958" # Ubuntu #19648
# Intel P4P800-MX (Ubuntu bug #5813)
switch_control "Master Playback Switch" on
switch_control "Master Surround" on
# Trident/YMFPCI/emu10k1:
unmute_and_set_level "Wave" "80%"
unmute_and_set_level "Music" "80%"
unmute_and_set_level "AC97" "80%"
# DRC:
unmute_and_set_level "Dynamic Range Compression" "80%"
# Required for HDA Intel (hda-intel):
unmute_and_set_level "Front" "80%"
# Required for SB Live 7.1/24-bit (ca0106):
unmute_and_set_level "Analog Front" "80%"
# Required at least for Via 823x hardware on DFI K8M800-MLVF Motherboard with kernels 2.6.10-3/4 (see ubuntu #7286):
switch_control "IEC958 Capture Monitor" off
# Required for hardware allowing toggles for AC97 through IEC958,
# valid values are 0, 1, 2, 3. Needs to be set to 0 for PCM1.
unmute_and_set_level "IEC958 Playback AC97-SPSA" "0"
# Required for newer Via hardware (see Ubuntu #31784)
unmute_and_set_level "VIA DXS,0" "80%"
unmute_and_set_level "VIA DXS,1" "80%"
unmute_and_set_level "VIA DXS,2" "80%"
unmute_and_set_level "VIA DXS,3" "80%"
# Required on some notebooks with ICH4:
switch_control "Headphone Jack Sense" off
switch_control "Line Jack Sense" off
# Some machines need one or more of these to be on;
# others need one or more of these to be off:
#
# switch_control "External Amplifier" on
switch_control "Audigy Analog/Digital Output Jack" on
switch_control "SB Live Analog/Digital Output Jack" on
# D1984 -- Thinkpad T61/X61
switch_control "Speaker" on
switch_control "Headphone" on
# HDA-Intel w/ "Digital" capture mixer (See Ubuntu #193823)
unmute_and_set_level "Digital" "80%"
return 0
}
# $1 <card ID> | "all"
sanify_levels()
{
TTSDML_RETURNSTATUS=0
case "$1" in
all)
for CARD in $(echo_card_indices) ; do
sanify_levels_on_card "$CARD" || TTSDML_RETURNSTATUS=1
done
;;
*)
sanify_levels_on_card "$1" || TTSDML_RETURNSTATUS=1
;;
esac
mute_and_zero_levels_on_card "pcsp"
return $TTSDML_RETURNSTATUS
}
# $1 <card ID>
preinit_levels_on_card()
{
CARDOPT="-c $1"
# Silly dance to activate internal speakers by default on PowerMac
# Snapper and Tumbler
id=`cat /proc/asound/card$1/id 2>/dev/null`
if [ "$id" = "Snapper" -o "$id" = "Tumbler" ]; then
switch_control "Auto Mute" off
switch_control "PC Speaker" off
switch_control "Auto Mute" on
fi
}
# $1 <card ID> | "all"
preinit_levels()
{
TTSDML_RETURNSTATUS=0
case "$1" in
all)
for CARD in $(echo_card_indices) ; do
preinit_levels_on_card "$CARD" || TTSDML_RETURNSTATUS=1
done
;;
*)
preinit_levels_on_card "$1" || TTSDML_RETURNSTATUS=1
;;
esac
return $TTSDML_RETURNSTATUS
}
# $1 <card ID>
mute_and_zero_levels_on_card()
{
CARDOPT="-c $1"
for CTL in \
Master \
PCM \
Synth \
CD \
Line \
Mic \
"PCM,1" \
Wave \
Music \
AC97 \
"Master Digital" \
DAC \
"DAC,0" \
"DAC,1" \
Headphone \
Speaker \
Playback
do
mute_and_zero_level "$CTL"
done
# for CTL in \
# "Audigy Analog/Digital Output Jack" \
# "SB Live Analog/Digital Output Jack"
# do
# switch_control "$CTL" off
# done
return 0
}
# $1 <card ID> | "all"
mute_and_zero_levels()
{
TTZML_RETURNSTATUS=0
case "$1" in
all)
for CARD in $(echo_card_indices) ; do
mute_and_zero_levels_on_card "$CARD" || TTZML_RETURNSTATUS=1
done
;;
*)
mute_and_zero_levels_on_card "$1" || TTZML_RETURNSTATUS=1
;;
esac
return $TTZML_RETURNSTATUS
}
# $1 <card ID> | "all"
card_OK()
{
[ "$1" ] || bugout
if [ "$1" = all ] ; then
[ -d /proc/asound ]
return $?
else
[ -d "/proc/asound/card$1" ] || [ -d "/proc/asound/$1" ]
return $?
fi
}
# If a card identifier is provided in $2 then regard it as an error
# if that card is not present; otherwise don't regard it as an error.
case "$1" in
start)
EXITSTATUS=0
TARGET_CARD="$2"
case "$TARGET_CARD" in
""|all) TARGET_CARD=all ; log_action_begin_msg "Setting up ALSA" ;;
esac
if ! card_OK "$TARGET_CARD"; then
[ "$TARGET_CARD" = "all" ] && log_action_end_msg "$( [ ! "$2" ] ; echo $? ; )" "none loaded"
exit $?
fi
preinit_levels "$TARGET_CARD" || EXITSTATUS=1
if ! restore_levels "$TARGET_CARD" ; then
sanify_levels "$TARGET_CARD" || EXITSTATUS=1
restore_levels "$TARGET_CARD" >/dev/null 2>&1 || :
fi
[ "$TARGET_CARD" = "all" ] && log_action_end_msg_and_exit "$EXITSTATUS"
exit $EXITSTATUS
;;
stop)
EXITSTATUS=0
TARGET_CARD="$2"
case "$TARGET_CARD" in
""|all) TARGET_CARD=all ; log_action_begin_msg "Shutting down ALSA" ;;
*) log_action_begin_msg "Shutting down ALSA card ${TARGET_CARD}" ;;
esac
card_OK "$TARGET_CARD" || log_action_end_msg_and_exit "$( [ ! "$2" ] ; echo $? ; )" "none loaded"
store_levels "$TARGET_CARD" || EXITSTATUS=1
mute_and_zero_levels "$TARGET_CARD" || EXITSTATUS=1
log_action_end_msg_and_exit "$EXITSTATUS"
;;
restart|force-reload)
EXITSTATUS=0
$0 stop || EXITSTATUS=1
$0 start || EXITSTATUS=1
exit $EXITSTATUS
;;
reset)
TARGET_CARD="$2"
case "$TARGET_CARD" in
""|all) TARGET_CARD=all ; log_action_begin_msg "Resetting ALSA" ;;
*) log_action_begin_msg "Resetting ALSA card ${TARGET_CARD}" ;;
esac
card_OK "$TARGET_CARD" || log_action_end_msg_and_exit "$( [ ! "$2" ] ; echo $? ; )" "none loaded"
preinit_levels "$TARGET_CARD"
sanify_levels "$TARGET_CARD"
log_action_end_msg_and_exit "$?"
;;
*)
echo "Usage: $MYNAME {start [CARD]|stop [CARD]|restart [CARD]|reset [CARD]}" >&2
exit 3
;;
esac